[% setvar title docs/pdds/pdd06_pasm.pod - Parrot Assembly Language %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='NAME'></a><h1>NAME</h1>
<p>docs/pdds/pdd06_pasm.pod - Parrot Assembly Language</p>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>This PDD describes the format of Parrot's bytecode assembly language.</p>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<p>Parrot's bytecode can be thought of as a form of machine language
for a virtual super CISC machine. It makes sense, then, to define an
assembly language for it for those people who may need to generate
bytecode directly, rather than indirectly via the perl (or any other)
language.</p>
<a name='IMPLEMENTATION'></a><h1>IMPLEMENTATION</h1>
<p>Parrot opcodes take the format of:</p>
<pre>  code destination[dest_key], source1[source1_key], source2[source2_key]</pre>
<p>The brackets do not denote optional arguments as such--they are real
brackets. They may be left out entirely, however. If any argument has
a key the assembler will substitute the null key for arguments missing keys.</p>
<p>Conditional branches take the format:</p>
<pre>  code boolean[bool_key], true_dest</pre>
<p>The key parameters are optional, and may be either an integer or a
string. If either is passed they are associated with the parameter to
their left, and are assumed to be either an array/list entry number,
or a hash key. Any time a source or destination can be a PMC register,
there may be a key.</p>
<p>Destinations for conditional branches are an integer offset from the
current PC.</p>
<p>All registers have a type prefix of P, S, I, or N, for PMC, string,
integer, and number respectively.</p>
<a name='Assembly Syntax'></a><h1>Assembly Syntax</h1>
<p>All assembly opcodes contain only ASCII lowercase letters, digits, and
the underscore.</p>
<p>Upper case names are reserved for assembler directives.</p>
<p>Labels all end with a colon. They may have ASCII letters, numbers, and
underscores in them. Labels that begin with a dollar sign (the only
valid spot in a label a dollar sign can appear) are private to the
subroutine they appear in.</p>
<p>Namespaces are noted with the NAMESPACE directive. It takes a single
parameter, the name of the namespace. Multilevel namespaces are
supported, and the namespaces should be double-colon separated.</p>
<p>Subroutine names are noted with the SUB directive. It takes a single
parameter, the name of the subroutine, which is added to the
namespace's symbol table. Sub names may be any valid Unicode
alphanumeric character and the underscore.</p>
<p>Constants don't need to be named and put in a separate section of the
assembly source. The assembler will take care of putting them in the
appropriate part of the generated bytecode.</p>
<a name='OPCODE LIST'></a><h1>OPCODE LIST</h1>
<p>In the following list, there may be multiple (but unlisted) versions
of an opcode. If an opcode takes a register that might be keyed, the
keyed version of the opcode has a _k suffix. If an opcode might take
multiple types of registers for a single parameter, the opcode
function really has a _x suffix, where x is either P, S, I, or N,
depending on whether a PMC, string, integer, or numeric register is
involved. The suffix isn't necessary (though not an error) as the
assembler can intuit the information from the code.</p>
<p>In those cases where an opcode can take several types of registers,
and more than one of the sources or destinations are of variable type,
then the register is passed in extended format. An extended format
register number is of the form:</p>
<pre>     register_number | register_type</pre>
<p>where register_type is 0x100, 0x200, 0x400, or 0x800 for PMC, string,
integer, or number respectively. So N19 would be 0x413.</p>
<p><b>Note</b>: Instructions tagged with a * will call a vtable method to
handle the instruction if used on PMC registers.</p>
<p>In all cases, the letters x, y, and z refer to register numbers. The
letter t refers to a generic register (P, S, I, or N). A lowercase p,
s, i, or n means either a register or constant of the appropriate type
(PMC, string, integer, or number)</p>
<a name='Control flow'></a><h2>Control flow</h2>
<p>The control flow opcodes check conditions and manage program flow.</p>
<ul>
<li><a name='if tx, ix'></a>if tx, ix</li>
<p>Check register tx. If true, branch by X.</p>
<li><a name='unless tx, ix'></a>unless tx, ix</li>
<p>Check register tx. If false, branch by X.</p>
<li><a name='jump tx'></a>jump tx</li>
<p>Jump to the address held in register x (Px, Sx, or Ix).</p>
<li><a name='branch tx'></a>branch tx</li>
<p>Branch forward or backward by the amount in register x. (X may be
either Ix, Nx, or Px) Branch offset may also be an integer constant.</p>
<li><a name='jsr tx'></a>jsr tx</li>
<p>Jump to the location specified by register X. Push the current
location onto the call stack for later returning.</p>
<li><a name='bsr ix'></a>bsr ix</li>
<p>Branch to the location specified by X (either register or label). Push
the current location onto the call stack for later returning.</p>
<li><a name='ret'></a>ret</li>
<p>Pop the location off the top of the stack and go there.</p>
</ul>
<a name='Data manipulation'></a><h2>Data manipulation</h2>
<p>These ops handle manipulating the data in registers</p>
<ul>
<li><a name='new Px, iy'></a>new Px, iy</li>
<p>Create a new PMC of class y stored in PMC register x.</p>
<li><a name='destroy Px'></a>destroy Px</li>
<p>Destroy the PMC in register X, leaving it undef</p>
<li><a name='set tx, ty'></a>set tx, ty</li>
<p>Copies y into x. Note that strings and PMCs are referred to by
pointer, so if you do something like:</p>
<pre>   set S0, S1</pre>
<p>this will copy the pointer in S1 into S0, leaving <b>both</b> registers
pointing at the same string.</p>
<li><a name='exchange tx, ty'></a>exchange tx, ty</li>
<p>Exchange the contents of registers X and Y, which must be of the same
type. (Generally cheaper than using the stack as an intermediary when
setting up registers for function calls)</p>
<li><a name='assign Px, ty'></a>assign Px, ty</li>
<p>Takes the contents of Y and assigns them into the existing PMC in X.</p>
<p>While set just copies pointers from one register to another, assign
actually does a value assignment, as:</p>
<pre>    $foo = $bar;</pre>
<p>X's assign vtable method is invoked and it does whatever is appropriate.</p>
<li><a name='clone Px, Py'></a>clone Px, Py</li>
<li><a name='clone Sx, xy'></a>clone Sx, xy</li>
<p>Performs a &quot;deeper&quot; copy of y into x, using the vtable appropriate
to the class of Py if cloning a PMC.</p>
<li><a name='tostring Sx, ty, Iz'></a>tostring Sx, ty, Iz</li>
<p>Take the value in register y and convert it to a string of type z,
storing the result in string register x.</p>
<li><a name='add tx, ty, tz *'></a>add tx, ty, tz *</li>
<p>Add registers y and z and store the result in register
x. (x = y + z) The registers must all be the same type, PMC, integer,
or number.</p>
<li><a name='sub tx, ty, tz *'></a>sub tx, ty, tz *</li>
<p>Subtract register z from register y and store the result in register
x. (x = y - z) The registers must all be the same type, PMC, integer,
or number.</p>
<li><a name='mul tx, ty, tz *'></a>mul tx, ty, tz *</li>
<p>Multiply register y by register z and store the results in register
x. The registers must be the same type.</p>
<li><a name='div tx, ty, tz *'></a>div tx, ty, tz *</li>
<p>Divide register y by register z, and store the result in register x.</p>
<li><a name='inc tx, nn *'></a>inc tx, nn *</li>
<p>Increment register x by nn. nn is an integer constant. If nn is
omitted, increment is 1.</p>
<li><a name='dec tx, nn *'></a>dec tx, nn *</li>
<p>Decrement register x by nn. nn is an integer constant. If nn is
omitted, decrement by 1.</p>
<li><a name='length Ix, Sy'></a>length Ix, Sy</li>
<p>Put the length of string y into integer register x.</p>
<li><a name='concat Sx, Sy'></a>concat Sx, Sy</li>
<p>Add string y to the end of string x.</p>
<li><a name='repeat Sx, Sy, iz'></a>repeat Sx, Sy, iz</li>
<p>Copies string y z times into string x.</p>
</ul>
<a name='Transcendental operations'></a><h2>Transcendental operations</h2>
<p>These opcodes handle the transcendental math functions. The
destination register here must always be either a numeric or a PMC
register.</p>
<ul>
<li><a name='sin nx, ty'></a>sin nx, ty</li>
<p>Return the sine of the number in Y</p>
<li><a name='cos nx, ty'></a>cos nx, ty</li>
<p>Return the cosine of the number in Y</p>
<li><a name='tan nx, ty'></a>tan nx, ty</li>
<p>Return the tangent of the number in Y</p>
<li><a name='sec nx, ty'></a>sec nx, ty</li>
<p>Return the secant of the number in Y</p>
<li><a name='atan nx, ty'></a>atan nx, ty</li>
<p>Return the arctangent of Y</p>
<li><a name='atan2 nx, ty'></a>atan2 nx, ty</li>
<p>Return the result of atan2 of Y</p>
<li><a name='asin nx, ty'></a>asin nx, ty</li>
<p>Return the arcsine of y</p>
<li><a name='acos nx, ty'></a>acos nx, ty</li>
<p>Return the arccosine of y</p>
<li><a name='asec nx, ty'></a>asec nx, ty</li>
<p>Return the arcsecant of y</p>
<li><a name='cosh nx, ty'></a>cosh nx, ty</li>
<p>Return the hyperbolic cosine of y</p>
<li><a name='sinh nx, ty'></a>sinh nx, ty</li>
<p>Return the hyperbolic sine of y</p>
<li><a name='tanh nx, ty'></a>tanh nx, ty</li>
<p>Return the hyperbolic tangent of y</p>
<li><a name='sech nx, ty'></a>sech nx, ty</li>
<p>Return the hyperbolic secant of y</p>
<li><a name='log2 nx, ty'></a>log2 nx, ty</li>
<p>Return the base 2 log of y</p>
<li><a name='log10 nx, ty'></a>log10 nx, ty</li>
<p>Return the base 10 log of y</p>
<li><a name='ln Nx, ty'></a>ln Nx, ty</li>
<p>Return the base e log of y</p>
<li><a name='log nx, ty, tz'></a>log nx, ty, tz</li>
<p>Return the base Z log of Y</p>
<li><a name='pow nx, ty, tz'></a>pow nx, ty, tz</li>
<p>Return Y to the Z power</p>
<li><a name='exp nx, ty'></a>exp nx, ty</li>
<p>Return e to the Y power</p>
</ul>
<a name='Register and stack ops'></a><h2>Register and stack ops</h2>
<p>These opcodes deal with registers and stacks</p>
<ul>
<li><a name='pushp'></a>pushp</li>
<p>Push the current set of PMC registers onto the register frame stack, and
start a new set (which will all initially be NULL). Register frames hold
only 16 registers, so we need to push two frames onto the stack. The
first frame holds the contents of registers 0-15; the second holds the
contents of registers 16-31.</p>
<li><a name='popp'></a>popp</li>
<p>Restore all of the PMC registers from the most recently <code>push</code>ed PMC
register frames. Since the register frames hold only 16 registers, we
pop two frames. We use the first frame to restore registers 16-31, and
the second frame to restore registers 0-15. Hence, <code>pushp</code> followed by
<code>popp</code> restores all of the PMC registers to their original state.</p>
<li><a name='poptopp'></a>poptopp</li>
<p>Pop a single PMC register frame off the PMC register frame stack and
use it to restore the values of registers 16-31. Registers 0-15 retain
their old values.</p>
<li><a name='popbottomp'></a>popbottomp</li>
<p>Pop a single PMC register frame off the PMC register frame stack and
use it to restore the values of registers 0-15. Registers 16-31 retain
their old values.</p>
<li><a name='pushi'></a>pushi</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?pushp'>pushp</a></i>, for the integer register set.</p>
<li><a name='popi'></a>popi</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?popp'>popp</a></i>, for the integer register set.</p>
<li><a name='poptopi'></a>poptopi</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?poptopp'>poptopp</a></i>, for the integer register set.</p>
<li><a name='popbottomi'></a>popbottomi</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?popbottomp'>popbottomp</a></i>, for the integer register set.</p>
<li><a name='pushs'></a>pushs</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?pushp'>pushp</a></i>, for the string register set.</p>
<li><a name='pops'></a>pops</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?popp'>popp</a></i>, for the string register set.</p>
<li><a name='poptops'></a>poptops</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?poptopp'>poptopp</a></i>, for the string register set.</p>
<li><a name='popbottoms'></a>popbottoms</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?popbottomp'>popbottomp</a></i>, for the string register set.</p>
<li><a name='pushn'></a>pushn</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?pushp'>pushp</a></i>, for the floating-point register set.</p>
<li><a name='popn'></a>popn</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?popp'>popp</a></i>, for the floating-point register set.</p>
<li><a name='poptopn'></a>poptopn</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?poptopp'>poptopp</a></i>, for the floating-point register set.</p>
<li><a name='popbottomn'></a>popbottomn</li>
<p>The same as <i><a href='http://search.cpan.org/perldoc?popbottomp'>popbottomp</a></i>, for the floating-point register set.</p>
<li><a name='clearp'></a>clearp</li>
<p>Clean out the current set of PMC registers, setting them to NULL</p>
<li><a name='cleari'></a>cleari</li>
<p>Clean out the current set of I registers, setting them to 0</p>
<li><a name='clears'></a>clears</li>
<p>Clean out the current set of S registers, setting them to NULL</p>
<li><a name='clearn'></a>clearn</li>
<p>Clean out the current set of N registers, setting them to 0</p>
<li><a name='null tx'></a>null tx</li>
<p>Set register X to a null value; for S and P registers, this will be NULL,
while for I and N registers it is 0</p>
<li><a name='save tx'></a>save tx</li>
<p>Push register or constant X onto the generic stack</p>
<li><a name='restore tx'></a>restore tx</li>
<p>Restore register X from the generic stack by popping off the topmost
entry. The type of this entry must match the register type.</p>
<li><a name='saveall'></a>saveall</li>
<p>Save all of the current set of registers onto the appropriate frame
stacks. Equivalent to performing a separate push for each register type.</p>
<li><a name='restoreall'></a>restoreall</li>
<p>Restore all of the registers from the appropriate frame stacks. Equivalent
to performing a separate pop for each register type.</p>
<li><a name='savetop'></a>savetop</li>
<p>As <i><a href='http://search.cpan.org/perldoc?saveall'>saveall</a></i> but only acts on registers 16-31.</p>
<li><a name='restoretop'></a>restoretop</li>
<p>As <i><a href='http://search.cpan.org/perldoc?restoreall'>restoreall</a></i> but only affects registers 16-31.</p>
<li><a name='set_warp string'></a>set_warp string</li>
<p>Sets a named marker for the stacks for later use.</p>
<li><a name='entrytype Ix, iy'></a>entrytype Ix, iy</li>
<p>Put the type of generic stack entry Y into integer register X</p>
<li><a name='depth Ix'></a>depth Ix</li>
<p>Get the current depth of the generic stack</p>
<li><a name='lookback tx, iy'></a>lookback tx, iy</li>
<p>Fetch the entry that's at position Y from the top of the generic stack. This
does not remove an entry from the stack, merely fetches the entry off it.</p>
<p>0 is the entry at the top of the stack, 1 is the entry immediately
previous to that, and so on. Entry -1 is the very bottom-most entry in
the stack. (While the stack may be a tree when looked at from the bottom up,
you don't have access to any other branches when looking this way).</p>
<li><a name='warp [string]'></a>warp [string]</li>
<p>Reset the current register stacks to the state they were in when the
warp was set. Resets only the frame pointers, doesn't guarantee the
contents of the registers. Be <i>very</i> careful modifying the frame
pointers by, for example, pushing register frames.</p>
<p>If a name is passed, warp back to the named point.</p>
<li><a name='unwarp'></a>unwarp</li>
<p>Reset the current register stacks to the state they were in before the
last warp.</p>
</ul>
<a name='Names, pads, and globals'></a><h2>Names, pads, and globals</h2>
<p>These operations are responsible for finding names in lexical or
global scopes, as well as storing data into those slots.  A static
scope is captured by a scratchpad.  The current dynamic scope is
represented by the state of the lexical stack (which contains
scratchpads).  For more detail on these ops see the inline POD
documentation in <b><i>ops/var.ops</i></b>.</p>
<ul>
<li><a name='new_pad ix'></a>new_pad ix</li>
<li><a name='new_pad Px, iy'></a>new_pad Px, iy</li>
<li><a name='push_pad Px'></a>push_pad Px</li>
<li><a name='pop_pad'></a>pop_pad</li>
<li><a name='pop_pad Px'></a>pop_pad Px</li>
<li><a name='peek_pad Px'></a>peek_pad Px</li>
<p>Instructions for creating scratchpads and manipulating the lexical
stack.</p>
<li><a name='store_lex sx, Py'></a>store_lex sx, Py</li>
<li><a name='store_lex ix, sy, Pz'></a>store_lex ix, sy, Pz</li>
<li><a name='store_lex ix, iy, Pz'></a>store_lex ix, iy, Pz</li>
<li><a name='find_lex Px, sy'></a>find_lex Px, sy</li>
<li><a name='find_lex Px, iy, sz'></a>find_lex Px, iy, sz</li>
<li><a name='find_lex Px, iy, iz'></a>find_lex Px, iy, iz</li>
<p>Instructions for storing in, and retrieving from the scratchpad
currently at the top of the lexical stack.  For each of these
operations there is an equivalent form that uses keyed versions of the
set instruction. The keyed variants require that a scratchpad be
specified rather than implicitly operating on the scratchpad on the
top of the stack.</p>
<li><a name='find_global Px, sy, sz'></a>find_global Px, sy, sz</li>
<p>Find the PMC for the global variable sy from the table sz and store it
in register X</p>
<li><a name='find_global Px, sy'></a>find_global Px, sy</li>
<p>Find the PMC for the global in the default table and put it in X.</p>
<li><a name='find_global_table Px, sy'></a>find_global_table Px, sy</li>
<p>Find the global symbol table Y and store its PMC in X</p>
<li><a name='find_global_slot ix, Py, sz'></a>find_global_slot ix, Py, sz</li>
<p>Find the slot in the global table Y for the global named Z, and store
its slot in register X.</p>
<li><a name='fetch_global Px, Py, iz'></a>fetch_global Px, Py, iz</li>
<p>Fetch the global in slot Z of the symbol table pointed to by Y</p>
<li><a name='store_global Px, sy'></a>store_global Px, sy</li>
<p>Store X in the default global symbol table with a name of Y.</p>
</ul>
<a name='Exceptions'></a><h2>Exceptions</h2>
<p>These opcodes deal with exception handling at the lowest
level. Exception handlers are dynamically scoped, and any exception
handler set in a scope will be removed when that scope is exited.</p>
<ul>
<li><a name='set_eh Px'></a>set_eh Px</li>
<p>Sets an exception handler in place. The code referred to by register
Px will get called if an exception is thrown while the exception
handler is in scope.</p>
<li><a name='clear_eh'></a>clear_eh</li>
<p>Clear out the most recently placed exception</p>
<li><a name='throw Px'></a>throw Px</li>
<p>Throw an exception represented by the object in PMC register x.</p>
<li><a name='rethrow Px'></a>rethrow Px</li>
<p>Only valid inside an exception handler. Rethrow the exception
represented by the object in PMC register x. This object may have been
altered by the exception handler.</p>
</ul>
<a name='Object things'></a><h2>Object things</h2>
<p>These opcodes deal with PMCs as objects, rather than as opaque data
items.</p>
<ul>
<li><a name='make_object Px, ty'></a>make_object Px, ty</li>
<p>Make the variable in PMC x an object of type ty. The type can be a
string, in which case we treat it as a package name.</p>
<li><a name='find_method Px, Py, tz'></a>find_method Px, Py, tz</li>
<p>Find the method Z for object Y, and return a PMC for it in X.</p>
<li><a name='call_method Px, ty'></a>call_method Px, ty</li>
<li><a name='find_attribute Px, sy'></a>find_attribute Px, sy</li>
<li><a name='set_attribute Px, ty, tz'></a>set_attribute Px, ty, tz</li>
<li><a name='can Ix, Py, sz'></a>can Ix, Py, sz</li>
<p>Sets X to TRUE if object Y can perform method Z; otherwise, X is set to
FALSE.</p>
<li><a name='does Ix, Py, sz'></a>does Ix, Py, sz</li>
<p>Sets X to TRUE if object Y can implements interface Z; otherwise, X is
set to FALSE.</p>
<li><a name='isa Px, ty'></a>isa Px, ty</li>
</ul>
<a name='Module handling'></a><h2>Module handling</h2>
<p>These opcodes deal with loading in bytecode or executable code
libraries, and fetching info about those libraries. This is all
dealing with precompiled bytecode or shared libraries.</p>
<ul>
<li><a name='load_bytecode sx'></a>load_bytecode sx</li>
<p>Load in the bytecode in file X. Search the library path if need be.</p>
<li><a name='load_opcode_lib sx, iy'></a>load_opcode_lib sx, iy</li>
<p>Load in the opcode library X, starting at opcode number Y. Search the
path if needed.</p>
<li><a name='load_string_lib sx'></a>load_string_lib sx</li>
<p>Load in the string handling library named X</p>
<li><a name='get_op_count sx'></a>get_op_count sx</li>
<p>Return the number of opcodes in opcode library X</p>
<li><a name='get_string_name sx'></a>get_string_name sx</li>
<p>Get the name of the string encoding that the library X handles</p>
<li><a name='find_string_lib sx, sy'></a>find_string_lib sx, sy</li>
<p>Find the string library that handles strings of type Y. Return its
name in X.</p>
</ul>
<a name='I/O operations'></a><h2>I/O operations</h2>
<p>Reads and writes read and write records, for some value of record.</p>
<ul>
<li><a name='new_fh px'></a>new_fh px</li>
<p>Create a new filehandle px</p>
<li><a name='open px, sy'></a>open px, sy</li>
<p>Open the file Y on filehandle X</p>
<li><a name='read px, py, pz'></a>read px, py, pz</li>
<p>Issue a read on the filehandle in y, and put the result in PMC
X. PMC Z is the sync object.</p>
<li><a name='write px, sy, pz'></a>write px, sy, pz</li>
<p>Write the string Y to filehandle X. PMC Z is the sync object.</p>
<li><a name='wait px'></a>wait px</li>
<p>Wait for the I/O operation represented by sync object X to finish</p>
<li><a name='readw px, py'></a>readw px, py</li>
<p>Read from filehandle Y and put the results in PMC X. Blocks until the
read completes.</p>
<li><a name='writew px, sy'></a>writew px, sy</li>
<p>Write string Y to filehandle X, waiting for the write to complete.</p>
<li><a name='seek px, ty'></a>seek px, ty</li>
<p>Seek filehandle X to position Y.</p>
<li><a name='tell tx, py'></a>tell tx, py</li>
<p>Return the current position of filehandle Y and put it in X. Returns
-1 for filehandles where this can't be determined. (Such as stream
connections)</p>
<li><a name='status px, py, tz'></a>status px, py, tz</li>
<p>Get informational item Z for filehandle Y and put the result in
X. This fetches things like the number of entries in the IO pipe,
number of outstanding I/O ops, number of ops on the filehandle, and so
forth.</p>
</ul>
<a name='Threading ops'></a><h2>Threading ops</h2>
<ul>
<li><a name='lock Px'></a>lock Px</li>
<p>Take out a high-level lock on the PMC in register X</p>
<li><a name='unlock Px'></a>unlock Px</li>
<p>Unlock the PMC in register X</p>
<li><a name='pushunlock Px'></a>pushunlock Px</li>
<p>Push an unlock request on the stack</p>
</ul>
<a name='Interpreter ops'></a><h2>Interpreter ops</h2>
<ul>
<li><a name='newinterp Px, flags'></a>newinterp Px, flags</li>
<p>Create a new interpreter in X, using the passed flags.</p>
<li><a name='runinterp Px, iy'></a>runinterp Px, iy</li>
<p>Jump into interpreter X and run the code starting at offset Y from the
current location. (This is temporary until we get something better)</p>
<li><a name='callout Pw, Px, sy, pz'></a>callout Pw, Px, sy, pz</li>
<p>Call routine Y in interpreter x, passing it the list of parameters
Z. W is a synchronization object returned. It can be waited on like
the sync objects returned from async I/O routines.</p>
<li><a name='interpinfo Ix, iy'></a>interpinfo Ix, iy</li>
<p>Get information item Y and put it in register X. Currently defined are:</p>
<ul>
<li><a name='1 TOTAL_MEM_ALLOC'></a>1 TOTAL_MEM_ALLOC</li>
<p>The total amount of system memory allocated for later parceling out
to Buffers. Doesn't include any housekeeping memory, memory for Buffer
or PMC structs, or things of that nature.</p>
<li><a name='2 DOD_RUNS'></a>2 DOD_RUNS</li>
<p>The total number of dead object detection runs that have been made.</p>
<li><a name='3 COLLECT_RUNS'></a>3 COLLECT_RUNS</li>
<p>The total number of memory collection runs that have been made.</p>
<li><a name='4 ACTIVE_PMCS'></a>4 ACTIVE_PMCS</li>
<p>The number of PMCs considered active. This means the DOD scan hasn't
noted them as dead.</p>
<li><a name='5 ACTIVE_BUFFERS'></a>5 ACTIVE_BUFFERS</li>
<p>The number of Buffers (usually STRINGs but could be other things)
considered active.</p>
<li><a name='6 TOTAL_PMCS'></a>6 TOTAL_PMCS</li>
<p>The total number of PMCs the interpreter has available. Includes both
active and free PMCs</p>
<li><a name='7 TOTAL_BUFFERS'></a>7 TOTAL_BUFFERS</li>
<p>The total number of Buffer structs the interpreter has available.</p>
<li><a name='8 HEADERS_ALLOC_SINCE_COLLECT'></a>8 HEADERS_ALLOC_SINCE_COLLECT</li>
<p>The number of new Buffer header block allocations that have been made since
the last DOD run. (Buffers, when allocated, are allocated in chunks)</p>
<li><a name='9 MEM_ALLOCS_SINCE_COLLECT'></a>9 MEM_ALLOCS_SINCE_COLLECT</li>
<p>The number of times we've requested a block of memory from the system
for allocation to Buffers since the last time we compacted the memory heap.</p>
</ul>
</ul>
<a name='Garbage collection'></a><h2>Garbage collection</h2>
<ul>
<li><a name='sweep'></a>sweep</li>
<p>Fire off a dead object sweep</p>
<li><a name='collect'></a>collect</li>
<p>Fire off a garbage collection sweep</p>
<li><a name='pausecollect'></a>pausecollect</li>
<p>Pause the garbage collector. No collections will be done for this interpreter
until the collector is unpaused.</p>
<li><a name='resumecollect'></a>resumecollect</li>
<p>Unpause the collector. This doesn't necessarily do a GC run, merely
allows the interpreter to fire one off when it deems it necessary.</p>
</ul>
<a name='Key operations'></a><h2>Key operations</h2>
<p>Keys are used to get access to individual elements of an aggregate
variable.  This is done to allow for opaque, packed, and
multidimensional aggregate types.</p>
<p>A key entry may be an integer, string, or PMC. Integers are used for
array lookups, strings for hash lookups, and PMCs for either.</p>
<ul>
<li><a name='new_key Sx'></a>new_key Sx</li>
<p>Create a new key structure and put a pointer to it in register X.</p>
<li><a name='clone_key Sx, ky'></a>clone_key Sx, ky</li>
<p>Make a copy of the key Y and put a pointer to it in register X. Y may
be either an S register or a constant.</p>
<li><a name='size_key Sx, iy'></a>size_key Sx, iy</li>
<p>Make the key structure X large enough to hold Y key entries</p>
<li><a name='key_size Ix, ky'></a>key_size Ix, ky</li>
<p>Put the number of elements in key Y into integer register X.</p>
<li><a name='toss_key Sx'></a>toss_key Sx</li>
<p>Nuke key X. Throws the structure away and invalidates the register.</p>
<li><a name='ke_type Ix, ky, iz'></a>ke_type Ix, ky, iz</li>
<p>Put the type of key Y's entry Z in register X. Current values are 0,
1, and 2 for Integer, String, and PMC, respectively.</p>
<li><a name='ke_value tx, ky, iz'></a>ke_value tx, ky, iz</li>
<p>Put the value from key Y, entry Z into register X.</p>
<li><a name='chop_key Sx'></a>chop_key Sx</li>
<p>Toss the topmost entry from key X.</p>
<li><a name='inc_key Sx, iy'></a>inc_key Sx, iy</li>
<p>Increment entry Y of key X by one.</p>
<li><a name='set_key Sw, [isp]x, iy[, iz]'></a>set_key Sw, [isp]x, iy[, iz]</li>
<p>Set key W, offset Y, to value X. If X is a PMC, then the fourth
operand must be specified. It can have a value of 0, 1, or 2,
corresponding to integer, string, or object. Aggregates use this to
figure out how to treat the key entry.</p>
</ul>
<a name='Properties'></a><h2>Properties</h2>
<p>Properties are a sort of runtime note attached to a PMC. Any PMC can
have properties on it. Properties live in a flat namespace, and they
are not in any way associated with the class of the PMC that they are
attached to.</p>
<p>Properties may be used for runtime notes on variables, or other
metadata that may change. They are not for object attributes.</p>
<ul>
<li><a name='setprop Px, sy, Pz'></a>setprop Px, sy, Pz</li>
<p>Set the property named Y of PMC X to the PMC in Z</p>
<li><a name='getprop Px, sy, Pz'></a>getprop Px, sy, Pz</li>
<p>Get the property named Y from PMC Z and put the result in register
X. Returns a NULL if the property doesn't exist.</p>
<li><a name='delprop Px, sy'></a>delprop Px, sy</li>
<p>Delete the property Y from PMC X</p>
<li><a name='prophash Px, Py'></a>prophash Px, Py</li>
<p>Fetch the properties from Y, put them in a Hash, and put the Hash in X.</p>
</ul>
<a name='Symbolic support for HLLs'></a><h2>Symbolic support for HLLs</h2>
<ul>
<li><a name='setline ix'></a>setline ix</li>
<p>Sets the 'current line' marker.</p>
<li><a name='setfile sx'></a>setfile sx</li>
<p>Sets the 'current file' marker.</p>
<li><a name='setpackage sx'></a>setpackage sx</li>
<p>Sets the 'current package' marker.</p>
<li><a name='getline ix'></a>getline ix</li>
<p>Fetches the 'current line' marker.</p>
<li><a name='getfile sx'></a>getfile sx</li>
<p>Fetches the 'current file' marker.</p>
<li><a name='getpackage sx'></a>getpackage sx</li>
<p>Fetches the 'current package' marker.</p>
</ul>
<a name='Foreign library access'></a><h2>Foreign library access</h2>
<p>These are the ops we use to load in and interface to non-parrot
libraries.</p>
<ul>
<li><a name='loadlib Px, Sy'></a>loadlib Px, Sy</li>
<p>Load in the library whose name is specified by y, and put a handle to
it into P register x.</p>
<li><a name='dlfunc Pw, Px, Sy, Sz'></a>dlfunc Pw, Px, Sy, Sz</li>
<p>Find a routine named Y, in library X (which you did, of course, open
with loadlib), and put a sub PMC onto W for it. You can call this sub
as if it were any other parrot subroutine.</p>
<p>Z has the function signature, which tells Parrot how to build the
interface from parrot (and parrot's calling conventions) to the
calling conventions of the library routine. Yes, this does mean that
you must know the function signature, but if you don't know that why
the heck would you be invoking the function, right?</p>
<p>The signature is a series of 1 or more characters, representing the
types for the call. The first character is the return type, while the
rest are the parameters. The types are:</p>
<ul>
<li><a name='Void. As a return type indicates that there is no return type. As a parameter indicates that there are no parameters. Can't be mixed with other parameter types.'></a>Void. As a return type indicates that there <i>is</i> no return type. As
a parameter indicates that there are no parameters. Can't be mixed
with other parameter types.</li>
<li><a name='Char. This is an integer type, taken from (or put into) an I register.'></a>Char. This is an integer type, taken from (or put into) an I register.</li>
<li><a name='short. An integer type, taken from 0 or put into an I register'></a>short. An integer type, taken from 0 or put into an I register</li>
<li><a name='int. An integer type.'></a>int. An integer type.</li>
<li><a name='long. An integer type. You know the drill.'></a>long. An integer type. You know the drill.</li>
<li><a name='float. F register denizen.'></a>float. F register denizen.</li>
<li><a name='double. F register, double-precision floating point type'></a>double. F register, double-precision floating point type</li>
<li><a name='PMC thingie. A generic pointer, taken from or stuck into a PMC's data pointer. If this is a return type, parrot will create a new UnManagedStruct PMC type, which is just a generic &quot;pointer so some damn thing or other&quot; PMC type which Parrot does no management of.'></a>PMC thingie. A generic pointer, taken from or stuck into a PMC's
data pointer. If this is a return type, parrot will create a new
UnManagedStruct PMC type, which is just a generic &quot;pointer so some
damn thing or other&quot; PMC type which Parrot does <i>no</i> management of.</li>
<li><a name='string pointer. Taken from, or stuck into, a string register. (Converted to a null-terminated C string before passing in)'></a>string pointer. Taken from, or stuck into, a string
register. (Converted to a null-terminated C string before passing in)</li>
</ul>
<p>So the signature for, for example, this SDL routine:</p>
<pre>   int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);</pre>
<p>would be <code>ipppp</code>, since it returns an integer and takes four
pointers. Presumably previous calls would have set those pointers up
properly.</p>
<p>Do note that parrot makes no guarantees as to the behaviour of the
libraries, and currently does no type checking on the input
parameters. We will fix that later.</p>
<p>The generated routine follows the calling conventions in PDD03. Note
that int, string, pmc, and float parameters are counted
separately. So if you have a signature of <code>ippiidd</code> the return goes
into I5, and the parameters come from P5, P6, I5, I6, N5, and N6,
respectively. A signature of <code>ipdiidp</code> has the identical same set of
registers used (and in the same order).</p>
<li><a name='invoke'></a>invoke</li>
<p>Invoke a subroutine in P0. Presumes that all the registers are set up
right for the call. The invoked subroutine <i>must</i> preserve any
registers that are not explicitly return parameters or calling
convention metadata parameters. (Such as the number of I reg
parameters, for example)</p>
</ul>
<a name='Runtime compilation'></a><h2>Runtime compilation</h2>
<p>These opcodes deal with runtime creation of bytecode and compilation
of source code.</p>
<ul>
<li><a name='compile Px, Py, Sz'></a>compile Px, Py, Sz</li>
<p>Compile source string Z, with compiler unit Y, and stick a handle to
a subroutine for the resulting bytecode segment (already loaded into
the current interpreter) into X.</p>
<p>Y is a assembler/compiler object of some sort, as registered with the
<b>compreg</b> opcode or the Parrot_compreg function. This will be something
like &quot;Perl5&quot;, &quot;Perl6&quot;, &quot;Perl5RE&quot;, &quot;Perl6RE&quot;, &quot;Python&quot;, &quot;Ruby&quot;... you get
the picture.</p>
<p>Parrot knows of a &quot;PASM1&quot; compiler, i.e. a one statement PASM compiler
implemented as PDB_eval. Imcc registers &quot;PASM&quot; and &quot;PIR&quot; compilers.</p>
<p>This is a high-level op, with the assumption that the resulting sub
will be called. It's the equivalent of perl 5's string eval, except
for the actual execution of the resulting code.</p>
<li><a name='compreg Px, Sy'></a>compreg Px, Sy</li>
<p>Get a compiler for source type Y.</p>
<li><a name='compreg Sx, Py'></a>compreg Sx, Py</li>
<p>Register the sub Y as a parser/compiler function named X. It will be
called whenever anyone invokes the compile op with the name X.</p>
</ul>
<a name='ATTACHMENTS'></a><h1>ATTACHMENTS</h1>
<p>None.</p>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<p>None.</p>
<a name='VERSION'></a><h1>VERSION</h1>
<p>None.</p>
<a name='CURRENT'></a><h2>CURRENT</h2>
<pre>    Maintainer: Dan Sugalski
    Class: Internals
    PDD Number: 6
    Version: 1.8
    Status: Developing
    Last Modified: 02 December 2002
    PDD Format: 1
    Language: English</pre>
<a name='HISTORY'></a><h2>HISTORY</h2>
<ul>
<li><a name='Version 1.8'></a>Version 1.8</li>
<p>December 11, 2002</p>
<li><a name='Version 1.7'></a>Version 1.7</li>
<p>December 02, 2002</p>
<li><a name='Version 1.6'></a>Version 1.6</li>
<p>November 05, 2001</p>
<li><a name='Version 1.5'></a>Version 1.5</li>
<p>October 12, 2001</p>
<li><a name='Version 1.4'></a>Version 1.4</li>
<p>September 24, 2001</p>
<li><a name='Version 1.3'></a>Version 1.3</li>
<p>September 12, 2001</p>
<li><a name='Version 1.2'></a>Version 1.2</li>
<p>August 25, 2001</p>
<li><a name='Version 1.1'></a>Version 1.1</li>
<p>August 8, 2001</p>
<li><a name='version 1'></a>version 1</li>
<p>None. First version</p>
</ul>
<a name='CHANGES'></a><h1>CHANGES</h1>
<ul>
<li><a name='Version 1.8'></a>Version 1.8</li>
<ul>
<li><a name='Added property ops'></a>Added property ops</li>
<li><a name='Fixed some bad register designations'></a>Fixed some bad register designations</li>
<li><a name='Opened up opcode name character list to include numbers'></a>Opened up opcode name character list to include numbers</li>
</ul>
<li><a name='Version 1.7'></a>Version 1.7</li>
<ul>
<li><a name='Fixed stack ops'></a>Fixed stack ops</li>
<p>push, pop, and clear properly documented according to the engine's
behaviour now.</p>
</ul>
<li><a name='Version 1.6'></a>Version 1.6</li>
<ul>
<li><a name='Added GC opcodes'></a>Added GC opcodes</li>
</ul>
<li><a name='Version 1.5'></a>Version 1.5</li>
<ul>
<li><a name='Now have a bsr in addition to a jsr'></a>Now have a bsr in addition to a jsr</li>
<li><a name='return is now ret'></a>return is now ret</li>
<li><a name='Added save and restore ops for saving and restoring individual registers'></a>Added save and restore ops for saving and restoring individual registers</li>
</ul>
<li><a name='Version 1.4'></a>Version 1.4</li>
<ul>
<li><a name='Conditional branches have just a true destination now'></a>Conditional branches have just a true destination now</li>
<li><a name='Added the I/O ops'></a>Added the I/O ops</li>
<li><a name='Added in the threading ops'></a>Added in the threading ops</li>
<li><a name='Added in the interpreter ops'></a>Added in the interpreter ops</li>
</ul>
<li><a name='Version 1.3'></a>Version 1.3</li>
<ul>
<li><a name='Added in the low-level module loading ops'></a>Added in the low-level module loading ops</li>
<li><a name='Added in transcendental functions and modulo'></a>Added in transcendental functions and modulo</li>
<li><a name='Finished the pad/global variable fetching bits'></a>Finished the pad/global variable fetching bits</li>
</ul>
<li><a name='Version 1.2'></a>Version 1.2</li>
<p>We have an interpreter now! Yay! (Okay, a simple one, but still...)
Changes made to reflect that.</p>
<li><a name='Version 1.1'></a>Version 1.1</li>
<ul>
<li><a name='Added in object'></a>Added in object</li>
<li><a name='Changed remnants of &quot;perl&quot; to &quot;Parrot&quot;'></a>Changed remnants of &quot;perl&quot; to &quot;Parrot&quot;</li>
<li><a name='Branch destination may be integer constant'></a>Branch destination may be integer constant</li>
<li><a name='Added &quot;Assembly Syntax&quot; section'></a>Added <i><a href='#Assembly Syntax'>&quot;Assembly Syntax&quot;</a></i> section</li>
</ul>
<li><a name='Version 1.0'></a>Version 1.0</li>
<p>None. First version</p>
</ul>
</div>
